﻿using Microsoft.ClearScript;
using Microsoft.ClearScript.JavaScript;
using Microsoft.ClearScript.V8;
using Newtonsoft.Json.Linq;
using OpenTK.Windowing.GraphicsLibraryFramework;
using System.Diagnostics;
using System.Runtime.InteropServices;
using ttbit;
using ttbit.form.impl;
using ttbit.Windows;

namespace env_otk
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var app = new App();

            var win = new GLPlatWin(app);

            win.Run();
        }
    }

    public static class TT
    {
        public static void WriteLine(string text) {
            Debug.WriteLine(text);

        }

        public static void SetEvent_Update(IJavaScriptObject _call)
        {
            if (_call.Kind == JavaScriptObjectKind.Function)
            {
                OnUpdate += (delta) =>
                {
                    _call.InvokeAsFunction(delta);
                };
            }
            //OnUpdate = _call;
        }
        public static void SetV(Microsoft.ClearScript.JavaScript.ITypedArray<byte> v)
        {
            byte[] data =v.ToArray();
        }
         static Action<float> OnUpdate;

        public static void _Update()
        {
            OnUpdate(0.1f);
        }
    }

    class App : IApp
    {
        public void OnExit()
        {
        }
        V8ScriptEngine v8env;
        //JsEnv jsEnv;
        GLPlatWin platWin;
        Graphics implGraph;
        public void OnInit(IPlatform platform, int x, int y, int w, int h)
        {
            int debugPort = 50443;
            v8env = new V8ScriptEngine(V8ScriptEngineFlags.EnableDebugging, debugPort);
            v8env.AllowReflection = true;
            v8env.AddHostType("TT", typeof(TT));
        
            v8env.Execute("main.js", @"
TT.WriteLine('hello world');
function onupdate(delta)
{
    TT.WriteLine('tick');
}
TT.SetEvent_Update(onupdate);
var u8 =new Uint8Array(5);
TT.SetV(u8);
");
            TT._Update(); 
            while(true)
            {
                TT._Update();
                System.Threading.Thread.Sleep(100);
            }
            return;
            //jsEnv = new JsEnv(new DefaultLoader(), 50443);//给个调试端口会崩溃，不知道从哪里查起？回头弄到Unity版本再看看吧，不造有没有可能魔改出问题了;

            //static bind 与回调 不和睦，咋回事

            //PuertsStaticWrap.AutoStaticCodeRegister.Register(jsEnv);
            //jsEnv.UsingAction<float>();
            //jsEnv.UsingAction<double>();
            //jsEnv.UsingAction<int>();
            //jsEnv.UsingAction<string>();

            //jsEnv.WaitDebugger();

            //赋予环境能力
            var ienv = new ttbit.form.impl.Env_OTK(platform);
            Env._Init(ienv);
            //TT2._Init(ienv);

            implGraph = Env.Graphic as Graphics;
            platWin = platform as GLPlatWin;

            platWin.Show();

            {
                //加载默认资源包，从默认资源包中找到所有的JS

                var indexitem = Env.RootPack.GetPackItem("index");
                var jsonindex = indexitem.GetAsText();
                var json = JObject.Parse(jsonindex);
                var scripts = json["script"] as JArray;
                foreach (string jsfile in scripts)
                {
                    var jscode = Env.RootPack.GetPackItem(Path.GetFileNameWithoutExtension(jsfile)).GetAsText();
                    //jsEnv.Eval(jscode, jsfile);
                }
            }
            //lib.bitform.test.Testor.Start();
            //while (true)
            //{
            //    System.Threading.Thread.Sleep(100);
            //    jsEnv.Tick();
            //    TT._Update(0.1f);
            //}




           

 
        }

        public void OnInputText(string text)
        {
        }

        public void OnKeyDown(Keys key, KeyModifiers modifier)
        {
        }

        public void OnKeyUp(Keys key, KeyModifiers modifier)
        {
            if (key == Keys.F8)
            {
                platWin.FrameDebug_OpenApp();
            }
        }

        public void OnPointEvent(int id, int x, int y, bool press)
        {
            if (id == 0 && press)
            {
                if (y < 24)
                    platWin.StartMouseDrag();
                else if (y > platWin.ClientHeight - 12 && x > platWin.ClientWidth - 12)
                    platWin.StartMouseScale(true, true);
                else if (y > platWin.ClientHeight - 12)
                    platWin.StartMouseScale(false, true);
                else if (x > platWin.ClientWidth - 12)
                    platWin.StartMouseScale(true, false);
            }

        }

        public void OnRender()
        {
            implGraph.Render();
        }

        public void OnResize(int x, int y, int w, int h)
        {
            implGraph.Resize(w, h);
            Env._OnChangeSize?.Invoke(w, h);
        }
        float ticktimer = 0;
        public void OnUpdate(double delta)
        {
            ticktimer += (float)delta;
            if (ticktimer > 0.5f)
            {
                ticktimer = 0;
                //jsEnv.Tick();
            }
            Env._OnUpdate((float)delta);
        }
    }
}